/*
 * Copyright (C) 2009-2018 Hangzhou 2Dfire Technology Co., Ltd. All rights reserved
 */
package com.ws.soa.consumer.config;


import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import com.google.common.collect.Maps;
import com.ws.soa.consumer.filter.CommonFilter;
import com.thetransactioncompany.cors.CORSFilter;
import com.ws.soa.consumer.filter.TokenFilter;
import com.ws.soa.consumer.payment.config.ApacheBuilderConfig;
import com.ws.soa.consumer.payment.config.WeChatConfig;
import com.ws.soa.consumer.payment.constant.Constants;
import com.ws.soa.consumer.payment.constant.MchPropertiesEnum;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextListener;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.EventListener;
import java.util.HashMap;

import javax.annotation.Resource;

import me.chanjar.weixin.common.util.http.apache.ApacheHttpDnsClientBuilder;

/**
 * GlobalConfig
 *
 * @author luobosi@2dfire.com
 * @since 2018-11-20
 */
@Configuration
@AutoConfigureAfter(TokenFilter.class)
public class GlobalConfig implements WebMvcConfigurer {

  @Resource
  private WeChatConfig weChatConfig;

  @Resource
  private ApacheBuilderConfig apacheBuilderConfig;

  @Resource
  private TokenFilter tokenFilter;

  /**
   * listener - addRequestContext
   */
  @Bean
  public ServletListenerRegistrationBean<EventListener> addRequestContextListener() {
    ServletListenerRegistrationBean<EventListener>
        registrationBean =
        new ServletListenerRegistrationBean<>();
    registrationBean.setListener(new RequestContextListener());
    registrationBean.setOrder(1);
    return registrationBean;
  }

  /**
   * filter - addCharacterEncoding
   */
  @Bean
  public FilterRegistrationBean<CharacterEncodingFilter> addCharacterEncodingFilter() {
    FilterRegistrationBean<CharacterEncodingFilter> registration = new FilterRegistrationBean<>();
    registration.setFilter(new CharacterEncodingFilter());
    registration.addInitParameter("encoding", "UTF-8");
    registration.addInitParameter("forceEncoding", "UTF-8");
    registration.addUrlPatterns("/*");
    registration.setOrder(1);
    return registration;
  }

  /**
   * filter - addToken
   */
  @Bean
  public FilterRegistrationBean addTokenFilter() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(tokenFilter);
    registration.addUrlPatterns("/*");
    registration.setOrder(2);
    return registration;
  }


  /**
   * filter - addCORS
   */
  @Bean
  public FilterRegistrationBean<CORSFilter> addCORSFilter() {
    FilterRegistrationBean<CORSFilter> registration = new FilterRegistrationBean<>();
    registration.setFilter(new CORSFilter());
    registration.addUrlPatterns("/*");
    registration.setOrder(2);
    return registration;
  }

  /**
   * filter - addCommon
   */
  @Bean
  public FilterRegistrationBean<CommonFilter> addCommonFilter() {
    FilterRegistrationBean<CommonFilter> registration = new FilterRegistrationBean<>();
    registration.setFilter(new CommonFilter());
    registration.addUrlPatterns("/*");
    registration.setOrder(3);
    return registration;
  }

  @Bean(name = "apacheHttpDnsClientBuilder")
  @ConditionalOnMissingBean
  public ApacheHttpDnsClientBuilder apacheHttpDnsClientBuilder() {
    ApacheHttpDnsClientBuilder apacheHttpDnsClientBuilder = ApacheHttpDnsClientBuilder.get();
    apacheHttpDnsClientBuilder
        .setConnectionRequestTimeout(this.apacheBuilderConfig.getConnectionRequestTimeout());
    apacheHttpDnsClientBuilder
        .setConnectionTimeout(this.apacheBuilderConfig.getConnectionTimeout());
    apacheHttpDnsClientBuilder.setIdleConnTimeout(this.apacheBuilderConfig.getIdleConnTimeout());
    apacheHttpDnsClientBuilder.setSoTimeout(this.apacheBuilderConfig.getSoTimeout());
    apacheHttpDnsClientBuilder.setCheckWaitTime(this.apacheBuilderConfig.getCheckWaitTime());
    apacheHttpDnsClientBuilder.setMaxConnPerHost(this.apacheBuilderConfig.getMaxConnPerHost());
    apacheHttpDnsClientBuilder.setMaxTotalConn(this.apacheBuilderConfig.getMaxTotalConn());
    return apacheHttpDnsClientBuilder;
  }

  @Bean(name = "wxPayFacadeHashMap")
  public HashMap<String, WxPayServiceImpl> wxPayFacadeHashMap(
      @Qualifier("apacheHttpDnsClientBuilder") ApacheHttpDnsClientBuilder apacheHttpDnsClientBuilder) {

    HashMap<String, WxPayServiceImpl> wxPayFacadeHashMap = Maps.newHashMap();
    WxPayConfig wxPayConfig = new WxPayConfig();
    wxPayConfig.setAppId(weChatConfig.getAppId());
    wxPayConfig.setMchId(MchPropertiesEnum.GOOD_DEEPS_MCH.getMchId());
    wxPayConfig.setMchKey(MchPropertiesEnum.GOOD_DEEPS_MCH.getMchKey());
    wxPayConfig.setKeyPath(Constants.Default.KEY_PATH);

    wxPayConfig.setNotifyUrl(Constants.Default.COMMON_PAY_CALLBACK_URL);
    wxPayConfig.setHttpConnectionTimeout(apacheBuilderConfig.getConnectionRequestTimeout());
    wxPayConfig.setHttpTimeout(apacheBuilderConfig.getConnectionTimeout());

    WxPayServiceImpl wxPayClientService = new WxPayServiceImpl();
    wxPayClientService.setConfig(wxPayConfig);

    wxPayFacadeHashMap.put(weChatConfig.getAppId(), wxPayClientService);
    return wxPayFacadeHashMap;
  }
}
